import { Queue } from "@/utils/quene";
import { IMoneyStrategy } from "../IMoneyStrategy";
import { RecmInfo, RoundInfo } from "../ExecutePlan";
import { EnumBetResult, EnumBjlResult } from "@/models/enums/EnumBjlResult";

export interface IRabbitMoneyOption {
    baseMoney: number;
    levelExteed: boolean,//true不受限制，false继续保持
    levelMap: number[][], //Array<Array<number>>,

}

export class WinRabbitMoneyStrategy implements IMoneyStrategy {
    option: IRabbitMoneyOption;
    strategyName: string = "";
    queue: Queue<number> = new Queue(3);
    debugCompoenent: string = "WinRabbitMoneyStrategyDebug";
    prevMoney: number = 0;
    lock: boolean = false;
    recmV: number = 0;
    recmMoney: number = 0;
    orecmV: number = 0;
    orecmMoney: number = 0;
    constructor(name?: string, option?: IRabbitMoneyOption) {
        this.strategyName = name ?? "GroupMoneyStrategy" + (new Date().getMilliseconds() + parseInt((Math.random() * 1000).toString()));
        this.resetStrategy();
        if (option) {
            this.option = option;
        }
        else {
            this.option = {
                baseMoney: 100,
                levelExteed: true,
                levelMap: [
                    [0, 3000, 6],
                    [3000, 6000, 7],
                    [6000, 9000, 8],
                    [9000, 12000, 9],
                    [12000, 15000, 9]
                ]
            };
        }
    }
    showMoney(roundInfo?: RoundInfo): [EnumBjlResult, number] {
        if (roundInfo) {
            if (this.orecmV != EnumBjlResult.U && roundInfo.reverse) {
                this.recmV = this.orecmV == EnumBjlResult.Z ? EnumBjlResult.X : EnumBjlResult.Z;
                this.recmMoney = this.orecmMoney;
            }
            else {
                this.recmV = this.orecmV;
                this.recmMoney = this.orecmMoney;
            }
        }

        return [this.recmV, this.recmMoney];
    }
    resetRecm(): void {
    }
    resetStrategy(): void {
        this.queue = new Queue<number>(3);
        this.queue.pushBack(0);
        this.queue.pushBack(100);
        this.queue.pushBack(100);
        this.recmV = EnumBjlResult.U;
        this.recmMoney = 0;
        this.lock = false;
        this.orecmV = EnumBjlResult.U;
        this.orecmMoney = 0;
    }

    toMoney(roundInfo: RoundInfo, recmInfo: RecmInfo, userRecm: RecmInfo, baseMoney: number): [EnumBjlResult, number] {
        let recmV = roundInfo.userRecm;
        let recmMoney = recmInfo.recmMoney;
        let winCount = recmInfo.roundSummaryInfo.winCount;
        let winMoney = recmInfo.roundSummaryInfo.winMoney - recmInfo.roundSummaryInfo.failMoney;
        if (recmInfo.summaryInfo.prevResult == EnumBetResult.Success) {
            if (!this.lock) {
                this.prevMoney = recmInfo.summaryInfo.winMoney - recmInfo.summaryInfo.failMoney;
                this.lock = true;
            }
            let pt: boolean = false;
            let max = Math.max(...this.option.levelMap.map(it => it[1]));
            let mapLevel = this.option.levelMap.filter(it => this.prevMoney >= it[0] && this.prevMoney < it[1]);
            if (mapLevel.length > 0 && winCount >= mapLevel[0][2]) {
                pt = true;
            }
            else if (this.prevMoney > max) {
                pt = false;
            }
            else if (this.prevMoney < 0 && winMoney >= (-this.prevMoney)) {
                pt = true;
            }
            else {
                pt = false;
            }

            if (pt) {
                recmMoney = (this.queue.get(2) ?? 0);
            }
            else {
                recmMoney = (this.queue.get(1) ?? 0) + (this.queue.get(2) ?? 0);
                //if (recmV != EnumBjlResult.U) this.queue.pushBack(recmMoney);
                this.queue.pushBack(recmMoney);
            }
        }
        else if (recmInfo.summaryInfo.prevResult == EnumBetResult.Fail) {
            this.lock = false;
            this.prevMoney = recmInfo.summaryInfo.winMoney - recmInfo.summaryInfo.failMoney;

            recmMoney = 100;
            this.queue = new Queue<number>(3);
            this.queue.pushBack(0);
            this.queue.pushBack(100);
            this.queue.pushBack(100);
            recmInfo.roundSummaryInfo.resetSummaryInfo();
        }
        else {
            recmMoney = (this.queue.get(2) ?? 0);
        }

        if (recmMoney < baseMoney) {
            recmMoney = baseMoney;
        }

        this.orecmV = recmV;
        this.orecmMoney = recmMoney;

        if (recmV != EnumBjlResult.U && roundInfo.reverse) {
            recmV = recmV == EnumBjlResult.Z ? EnumBjlResult.X : EnumBjlResult.Z;
        }
        this.recmV = recmV;
        this.recmMoney = recmMoney;
        return [recmV, recmMoney];

    }

    copyValue(valueObj: any): void {
        let obj = valueObj as WinRabbitMoneyStrategy;
        if (obj) {
            this.debugCompoenent = obj.debugCompoenent;
            //Object.assign(this.option, obj.option)
            this.queue.copyValue(obj.queue);
            this.prevMoney = obj.prevMoney;
            this.lock = obj.lock;
            this.recmV = obj.recmV;
            this.recmMoney = obj.recmMoney;
            this.orecmV = obj.orecmV;
            this.orecmMoney = obj.orecmMoney;
            //this.queue.Size = obj.queue.Size;
        }

    }
}


export class WinRabbitMoneyStrategyV2 implements IMoneyStrategy {
    option: IRabbitMoneyOption;
    strategyName: string = "";
    queue: Queue<number> = new Queue(3);
    debugCompoenent: string = "WinRabbitMoneyStrategyDebug";
    prevMoney: number = 0;
    lock: boolean = false;
    top: boolean = false;

    recmV: number = 0;
    recmMoney: number = 0;
    orecmV: number = 0;
    orecmMoney: number = 0;
    constructor(name?: string, option?: IRabbitMoneyOption) {
        this.strategyName = name ?? "GroupMoneyStrategy" + (new Date().getMilliseconds() + parseInt((Math.random() * 1000).toString()));
        this.resetStrategy();
        if (option) {
            this.option = option;
        }
        else {
            this.option = {
                baseMoney: 50,
                levelExteed: true,
                levelMap: [
                    [-30000, 0, 6],
                    [0, 3000, 6],
                    [3000, 6000, 7],
                    [6000, 9000, 8],
                    [9000, 12000, 9],
                    [12000, 15000, 9]
                ]
            };
        }
    }
    showMoney(roundInfo?: RoundInfo): [EnumBjlResult, number] {
        if (roundInfo) {
            if (this.orecmV != EnumBjlResult.U && roundInfo.reverse) {
                this.recmV = this.orecmV == EnumBjlResult.Z ? EnumBjlResult.X : EnumBjlResult.Z;
                this.recmMoney = this.orecmMoney;
            }
            else {
                this.recmV = this.orecmV;
                this.recmMoney = this.orecmMoney;
            }
        }

        return [this.recmV, this.recmMoney];
    }
    resetRecm(): void {
        this.resetStrategy();
    }
    resetStrategy(): void {
        this.queue = new Queue<number>(3);
        this.queue.pushBack(0);
        this.queue.pushBack(100);
        this.queue.pushBack(100);

        this.lock = false;
        this.top = false;

        this.recmV = EnumBjlResult.U;
        this.recmMoney = 0;
        this.orecmV = EnumBjlResult.U;
        this.orecmMoney = 0;
    }

    toMoney(roundInfo: RoundInfo, recmInfo: RecmInfo, userRecm: RecmInfo, baseMoney: number): [EnumBjlResult, number] {
        let recmV = roundInfo.userRecm;
        let recmMoney = recmInfo.recmMoney;
        let winCount = recmInfo.roundSummaryInfo.winCount;
        let winMoney = recmInfo.roundSummaryInfo.winMoney - recmInfo.roundSummaryInfo.failMoney;
        if (recmInfo.summaryInfo.prevResult == EnumBetResult.Success) {
            if (!this.lock) {
                this.prevMoney = recmInfo.summaryInfo.winMoney - recmInfo.summaryInfo.failMoney;
                this.lock = true;
            }
            let pt: boolean = false;
            let max = Math.max(...this.option.levelMap.map(it => it[1]));
            let mapLevel = this.option.levelMap.filter(it => this.prevMoney >= it[0] && this.prevMoney < it[1]);
            if (mapLevel.length > 0 && winCount >= mapLevel[0][2]) {
                pt = true;
            }
            else if (this.prevMoney > max) {
                pt = false;
            }
            // else if (this.prevMoney < 0 && winMoney >= (-this.prevMoney)) {
            //     pt = true;
            // }
            else {
                pt = false;
            }

            if (pt && !this.top) {
                //recmMoney = (this.queue.get(2) ?? 0);
                this.top = true;
                for (let i = 0; i < 2; i++) {
                    let v = (this.queue.get(1) ?? 0) - (this.queue.get(0) ?? 0);
                    this.queue.pushFront(v);
                }
                recmMoney = (this.queue.get(2) ?? 0);
                this.lock = false;
            }
            else {
                recmMoney = (this.queue.get(1) ?? 0) + (this.queue.get(2) ?? 0);
                //if (recmV != EnumBjlResult.U) this.queue.pushBack(recmMoney);
                this.queue.pushBack(recmMoney);
            }
        }
        else if (recmInfo.summaryInfo.prevResult == EnumBetResult.Fail) {
            this.lock = false;
            this.top = false;
            this.prevMoney = recmInfo.summaryInfo.winMoney - recmInfo.summaryInfo.failMoney;

            recmMoney = 10;
            this.queue = new Queue<number>(3);
            this.queue.pushBack(0);
            this.queue.pushBack(100);
            this.queue.pushBack(100);
            recmInfo.roundSummaryInfo.resetSummaryInfo();
        }
        else {
            recmMoney = (this.queue.get(2) ?? 0);
        }

        if (recmMoney < baseMoney) {
            recmMoney = baseMoney;
        }

        this.orecmV = recmV;
        this.orecmMoney = recmMoney;

        if (recmV != EnumBjlResult.U && roundInfo.reverse) {
            recmV = recmV == EnumBjlResult.Z ? EnumBjlResult.X : EnumBjlResult.Z;
        }
        this.recmV = recmV;
        this.recmMoney = recmMoney;

        return [recmV, recmMoney];

    }

    copyValue(valueObj: any): void {
        let obj = valueObj as WinRabbitMoneyStrategyV2;
        if (obj) {
            this.debugCompoenent = obj.debugCompoenent;
            //Object.assign(this.option, obj.option)
            this.queue.copyValue(obj.queue);
            this.prevMoney = obj.prevMoney;
            this.lock = obj.lock;
            this.top = obj.top;

            this.recmV = obj.recmV;
            this.recmMoney = obj.recmMoney;
            this.orecmV = obj.orecmV;
            this.orecmMoney = obj.orecmMoney;
            //this.queue.Size = obj.queue.Size;
        }

    }
}